package org.hxyjs.service.impl;

import org.hxyjs.dao.*;
import org.hxyjs.dto.DTO;
import org.hxyjs.dto.MessageEnum;
import org.hxyjs.entity.*;
import org.hxyjs.page.PageInfo;
import org.hxyjs.service.OrderFormService;
import org.hxyjs.utils.DateUtils;
import org.hxyjs.vo.GrabVo;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.*;
import java.util.stream.Stream;

@Service("OrderFormService")
public class OrderFormServiceImpl implements OrderFormService {
    @Resource
    OrderFormDao orderFormDao;
    @Resource
    OrderFormItemDao orderFormItemDao;
    @Resource
    MongodbDao mongodbDao;
    @Resource
    RedisDao redisDao;
    @Resource
    RestaurantForOrder restaurantForOrder;
    @Resource
    UserDaoForOrder userDaoForOrder;

    @Override
    public DTO<OrderForm> getAllOrderForms() throws Exception {
        List<OrderForm> orderForms = orderFormDao.getAllOrderForms();
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum = Optional.ofNullable(orderForms).isPresent() ? MessageEnum.GETADMINSUCCESS : MessageEnum.GETADMINFAIL;
        return new DTO<OrderForm>(messageEnum.getCode(), messageEnum.getMessage(), orderForms);
    }

    @Override
    public DTO<OrderForm> deleteOrderFormByUrno(String urno) throws Exception {
        Integer result = orderFormDao.deleteOrderFormByUrno(urno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum = result > 0 ? MessageEnum.DELETEADMINSUCCESS : MessageEnum.DELETEADMINFAIL;
        return new DTO<OrderForm>(messageEnum.getCode(), messageEnum.getMessage());
    }

    @Override
    public DTO<OrderForm> updateOrderFormByUrno(OrderForm orderForm) throws Exception {
        Integer result = orderFormDao.updateOrderFormByUrno(orderForm);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum = result > 0 ? MessageEnum.UPDATEADMINSUCCESS : MessageEnum.UPDATEADMINFAIL;
        return new DTO<OrderForm>(messageEnum.getCode(), messageEnum.getMessage());
    }

    /**
     * 支付成功添加订单订单项到mysql
     *
     * @param urno
     * @return
     * @throws Exception
     */
    @Transactional
    public DTO<OrderForm> processPay(String urno) throws Exception {
        MongoDBDocument<OrderForm> mongoDBDocument = mongodbDao.findByKey("OrderFormWithOrderItem", urno, MongoDBDocument.class);
        DTO<OrderForm> dto = null;
        String oldUrno = new String(urno);

        System.out.println(urno);
        if (Optional.ofNullable(mongoDBDocument).isPresent()) {
            OrderForm orderForm = mongoDBDocument.getT();
            urno = orderFormDao.initId(orderForm.getUno() + orderForm.getRno());
            orderForm.setUrno(urno);
            orderForm.setUresState("已付款");
            Integer result = orderFormDao.addOrderForm(orderForm);
            //如果订单成功就添加订单详情

            if (result > 0) {
                String begin = orderForm.getUrno();
                Stream.iterate(0, i -> i + 1).limit(orderForm.getOrderformitems().size()).forEach(i -> {
                    Orderformitem orderformitem = orderForm.getOrderformitems().get(i);
                    String oino = null;
                    if (i < 10) {
                        oino = begin + 0 + (i + 1);

                    } else {
                        oino = begin + (i + 1);
                    }
                    orderformitem.setOino(oino);
                    orderformitem.setUrno(orderForm.getUrno());
                });
                result = orderFormItemDao.addOrderformitems(orderForm.getOrderformitems());

            }
            User userByUno = userDaoForOrder.getUserByUno(orderForm.getUno());
            List<OrderForm> orderForms = new ArrayList<>();
            orderForms.add(orderForm);
            userByUno.setOrderForms(orderForms);//将当前订单信息放入当前用户对象
            dto = result > 0 ? new DTO(200, "支付成功", userByUno) : new DTO(403, "支付失败");
            mongodbDao.removeById(oldUrno, "OrderFormWithOrderItem");
            mongodbDao.save(new MongoDBDocument(orderForm.getUrno(), orderForm));
        } else {
            dto = new DTO(403, "非法操作");
        }
        return dto;

    }


    /**
     * 用户下订单默认状态为待处理保存到redis（redis只有订单基本信息）MongoDB带有订单项和饭店信息（方便生成对应的cookie时带有订单信息）
     *
     * @param orderForm
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DTO<OrderForm> addOrderForm(OrderForm orderForm) throws Exception {
        MessageEnum messageEnum = MessageEnum.ADDADMINSUCCESS;
        DTO<OrderForm> dto  = new DTO<OrderForm>(messageEnum.getCode(),messageEnum.getMessage());
        Optional<GrabVo> grabVoOp = Optional.ofNullable(redisDao.get(orderForm.getRno(), GrabVo.class));
        System.out.println("111111");


//        System.out.println(grabVoOp.get().getDates());

        Set<String> datesBetweenTwoDate = DateUtils.getDatesBetweenTwoDate(orderForm.getUresdate(), orderForm.getUresendDate());
        boolean flag = false;//默认下单成功，
        if (grabVoOp.isPresent()) {// 如果redis中没有该厨师的信息就成功
            System.out.println(grabVoOp.get().getDates());

            for (String date : grabVoOp.get().getDates()) {
                System.out.println("2222222");
                for (String grabDate : datesBetweenTwoDate) {
                    if (date.equals(grabDate)) {
                        System.out.println("33333333333");
                        flag = true;
                        break;
                    }

                }
                System.out.println("-----55555-----");
                if (flag){
                 dto.setCode(403);
                 dto.setMsg("同一时间他人已下单，下单失败");
                  System.out.println("下单失败");
                    break;
                }

            }

        }
        if(!flag) {

            GrabVo grabVo = grabVoOp.orElse(new GrabVo());
            grabVo.setRno(orderForm.getRno());

            grabVo.getDates().addAll(datesBetweenTwoDate);

            //未付款订单的订单号都是临时订单号由MongoDB产生的而付款的订单号由mysql产生
            String tempeUrno = mongodbDao.initId(orderForm.getUno() + orderForm.getRno(), "_id", "OrderFormWithOrderItem");

            orderForm.setUrno(tempeUrno);
            OrderForm orderFormRedis = new OrderForm();
            orderFormRedis.setUrno(orderForm.getUrno());
            orderFormRedis.setUresdate(orderForm.getUresdate());
            orderFormRedis.setUresendDate(orderForm.getUresendDate());
            orderFormRedis.setRno(orderForm.getRno());
            redisDao.save(orderForm.getUrno(), orderFormRedis, 3600L);
            Restaurant restaurantByRno = restaurantForOrder.getRestaurantByRno(orderForm.getRno());
            orderForm.setRestaurant(restaurantByRno);
            System.out.println(restaurantByRno);
            MongoDBDocument<OrderForm> mongoDBDocument = new MongoDBDocument(orderForm.getUrno(), orderForm);
            //将最新的内容录入mongodb
            mongodbDao.save(mongoDBDocument, "OrderFormWithOrderItem");
            messageEnum = MessageEnum.ADDADMINSUCCESS;
            redisDao.saveJson(orderForm.getRno(), grabVo, 3600L);

        }
        System.out.println(dto);
        return dto;

    }


    /**
     * 学生选课成功 学生成绩加1分，从选课信息中可以获得学生的学号就能查询出学生原来的成绩
     *
     * @param
     * @return
     * @throws Exception
     */
    @Override
    public DTO<OrderForm> getOrderFormByUrno(String urno) throws Exception {
        OrderForm orderForms = orderFormDao.getOrderFormByUrno(urno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum = Optional.ofNullable(orderForms).isPresent() ? MessageEnum.GETADMINSUCCESS : MessageEnum.GETADMINFAIL;
        return new DTO<OrderForm>(messageEnum.getCode(), messageEnum.getMessage(), orderForms);
    }

    @Override
    public DTO<OrderForm> getOrderFormByPage(PageInfo pageInfo) throws Exception {
        List<OrderForm> orderForms = orderFormDao.getOrderFormByPage(pageInfo);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum = Optional.ofNullable(orderForms).isPresent() ? MessageEnum.GETADMINSUCCESS : MessageEnum.GETADMINFAIL;
        return new DTO<OrderForm>(messageEnum.getCode(), messageEnum.getMessage(), orderForms, pageInfo);
    }

    @Cacheable(value = "myCache", key = "#cacheId")
    @Override
    public DTO<OrderForm> getOrderFormByPage(PageInfo pageInfo, String cacheId) throws Exception {
        List<OrderForm> orderForms = orderFormDao.getOrderFormByPage(pageInfo);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum = Optional.ofNullable(orderForms).isPresent() ? MessageEnum.GETADMINSUCCESS : MessageEnum.GETADMINFAIL;
        return new DTO<OrderForm>(messageEnum.getCode(), messageEnum.getMessage(), orderForms, pageInfo);
    }

    /**
     * 饭店确认订单需要删除redis 中未确认的订单更新mongoDB中对应订单状态为确认，如果是拒绝也要删除redis中未确认的订单，更新mongoDB中对应订单状态为拒绝
     * * @param urno
     *
     * @param type
     * @return
     * @throws Exception
     */
    @Override
    public DTO<OrderForm> processOrder(String urno, String type) throws Exception {
        redisDao.delete(urno);
        String processResult = type.equals("allow") ? "待付款" : "取消";
        System.out.println("111--");
        mongodbDao.updateByKey("OrderFormWithOrderItem", urno, OrderForm.class, "t.uresState", processResult);
        return new DTO<>(200, "订单确认成功");
    }
}
